home *** CD-ROM | disk | FTP | other *** search
- /* Copyright, 1990, Regents of the University of Colorado */
- /* This program is a fairly long example, designed to show that complex programs
- * can be written in DINO. */
-
- /****************************************************************************
- * Solves system of linear equations with a block bordered structure
- * (See Rosin, Schnabel, and Weaver's "Expressing Complex Parallel
- * Algorithms in Dino" p. 2).
- *
- * General Form:
- *
- * A1 B x1 f1
- * A2 B x2 f2
- * .. .. * .. = ..
- * Aq Bq xq fq
- * C C .. Cq P xqp fqp
- *
- * Where:
- *
- * A is nxn
- * B is nxm
- * C is mxn
- * P is mxm
- * x is nx1
- * xqp is mx1
- * f is nx1
- * fqp is mx1
- *
- * Command Line:
- *
- * block <filename>
- *
- * where <filename> is the name of the file describing the linear system
- * as specified in function read_data.
- ***************************************************************************/
-
- #include <stdio.h>
- #include <math.h>
- #include <string.h> /* ==> Standard include files can be used
- in the normal manner. */
-
- #include "dino.h" /* ==> The directory containing dino.h is
- automatically searched. */
-
- map byRow = [block][compress];
- map byBlock = [block];
- map byElement = [block];
- map byCol = [compress][block];
-
- #define N 2
- #define M 3
- #define Q 2
-
- environment solve[M:id] {
-
- composite form_J( in sumCW, P )
- double distributed sumCW[M][M] map byRow;
- double distributed P[M][M] map byRow;
- {
- int i;
- for( i=0; i<M; i++ )
- P[id][i] = P[id][i] - sumCW[id][i];
- };
-
- composite form_b( b, in sumCz, in fqp )
- double distributed b[M] map byElement;
- double distributed sumCz[M] map byElement;
- double distributed fqp[M] map byElement;
- {
- b[id] = fqp[id] - sumCz[id];
- };
-
- composite dist_lu( A, RowPerm )
- double distributed A[M][M] map byCol;
- int distributed RowPerm[M] map all;
- {
- double distributed Mult[M] map all;
- int i, j, k, pivrow;
- double piv, temp;
-
- RowPerm[M-1] = M-1;
- for( k=0; k<M-1; k++ ) {
- if( k == id ) {
- /* select pivot and swap in pivot column */
- piv = A[k][k];
- pivrow = k;
-
- /* find largest row element in kth column (partial pivot) */
- for( i=k+1; i<M; i++ )
- if( fabs(A[i][k]) > piv ) {
- piv = A[i][k];
- pivrow = i;
- }
-
- /* swap row position in kth column */
- if( pivrow != k ) {
- temp = A[k][k];
- A[k][k] = A[pivrow][k];
- A[pivrow][k] = temp;
- }
-
- /* calculate l (multipliers) and row swap info. */
- RowPerm[k] = pivrow;
- for (i=k+1; i<M; i++)
- Mult[i] = A[i][k] /= -A[k][k];
-
- /* broadcast Mult and RowPerm */
- Mult[<k+1, M-1>]#{ solve[] - solve[id] } = Mult[<k+1, M-1>];
- RowPerm[k]#{ solve[] - solve[id] } = RowPerm[k];
- }
-
- else {
- /* receive broadcast here */
- Mult[<k+1, M-1>] = Mult[<k+1, M-1>]#{ solve[k] };
- RowPerm[k] = RowPerm[k]#{ solve[k] };
- }
-
- /* eliminate in your column greater than k */
- pivrow = RowPerm[k];
- if( id>k ) {
- if( pivrow != k ) {
- temp = A[k][id];
- A[k][id] = A[pivrow][id];
- A[pivrow][id] = temp;
- }
- for( i=k+1; i<M; i++ )
- A[i][id] += Mult[i]*A[k][id]; /* was k */
- }
- /* swap factors in lower triangular */
- else if( id<k )
- for( i=k; i<M; i++ ) {
- temp = A[i][id];
- A[i][id] = A[pivrow][id];
- A[pivrow][id] = temp;
- }
- }
- };
-
- composite dist_solve( in lu, out x, in b, in RowPerm )
- double distributed lu[M][M] map byRow;
- double distributed x[M] map byElement;
- double distributed b[M] map all;
- int distributed RowPerm[M] map all;
- {
- double distributed y[M] map byElement;
- double temp;
- int i, swap;
-
- /* permute b according to RowPerm */
- for( i=0; i<=M-2; i++ ) {
- swap = RowPerm[i];
- if( swap != i ) {
- temp = b[i];
- b[i] = b[swap];
- b[swap] = temp;
- }
- }
-
- /* solve ly = b */
- y[id] = b[id];
- for( i=0; i<=id-1; i++ )
- y[id] += lu[id][i]*y[i]#{solve[i]};
- y[id]#{solve[<id+1,M-1>]} = y[id];
-
- /* solve ux=y */
- x[id] = y[id];
- for( i=M-1; i>id; i-- )
- x[id] -= lu[id][i]*x[i]#{solve[i]};
- x[id] = x[id] / lu[id][id];
- x[id]#{solve[<0,id-1>]} = x[id];
- };
- }
-
- environment node[Q:id] {
-
- map slice = [block][compress][compress];
-
- double distributed W[Q][N][M] map slice; /* = A^-1 B*/
- double distributed z[Q*N] map byBlock;
- /* ==> Distributed variables may be declared
- inside an environment, in which case
- they are accessable by all functions and
- composite procedures within that
- environment. */
-
- /*
- * negate v of length l
- */
- neg_vec( v,l )
- double v[];
- int l;
- {
- int i;
- for( i=0; i<=l-1; i++ )
- v[i] = v[i] * -1.0;
- };
-
- /*
- * v will contain (v - x) where v & x are 1 x l
- */
- sub_vec( v,x,l ) /* v <= v - x, l is length of vectors */
- double v[];
- double x[];
- int l;
- {
- int i;
- for( i=0; i<=l-1; i++ )
- v[i] = v[i] - x[i];
- };
-
- /*
- * v will contain (v - x) where v & x are 1 x l
- */
- add_vec( v,x,l ) /* v <= v - x, l is length of vectors */
- double v[];
- double x[];
- int l;
- {
- int i;
- for( i=0; i<=l-1; i++ )
- v[i] = v[i] + x[i];
- };
-
- /*
- * returns (A*B) where A is mxn and B nxm and T is mxm
- */
- mat_mat_mult(A,B,T)
- double A[M][N], B[N][M], T[M][M];
- {
- int row, col, i;
- for( row=0; row<=M-1; row++ )
- for( col=0; col<=M-1; col++ ) {
- T[row][col] = 0;
- /* inner product */
- for( i=0; i<=N-1; i++ )
- T[row][col] += A[row][i]*B[i][col];
- }
- };
-
- /*
- * Does lu decomposition on matrix A
- * Note: o uses partial pivoting
- * o assume A is nxn since seq_lu is only used on A to find z
- * (see above mentioned paper)
- * o after call to seq_lu A will contain lu decomposition
- */
- void seq_lu( A, p )
- double A[N][N];
- int *p;
- {
- double temp, mult;
- int i, diag, col, pivot;
- for( diag=0; diag<=N-2; diag++ ) {
-
- /* look for largest leading row element, i.e. pivot */
- pivot = diag;
- for( i=diag; i<=N-1; i++ ) {
- if( A[i][diag] > A[pivot][diag] )
- pivot = i;
- }
- p[diag] = pivot;
-
- /* new pivot found? */
- if( pivot != diag ) {
- /* information about row swaps stored in p such that
- p[diag] = pivot means that row pivot and diag were
- swapped at diagth iteration */
- for( i=0; i<=N-1; i++ ) { /* swap rows */
- temp = A[diag][i];
- A[diag][i] = A[pivot][i];
- A[pivot][i] = temp;
- }
- }
-
- /* elimate leading columns */
- for( i=diag+1; i<=N-1; i++ ) {
- /* compute l */
- mult = A[i][diag] /= -A[diag][diag];
- for( col=diag+1; col<=N-1; col++ )
- A[i][col] += mult*A[diag][col];
- }
- }
- p[N-1] = N-1; /* last row can't be swapped at last iteration */
- };
-
- /*
- * solves: lu x = b
- * Note: o lu is nxn (see seq_lu) and naturally x, b are 1xn
- * o result found in x after call to seq_solve
- */
- void seq_solve( lu, x, b, p ) /* solves lu x = b */
- double lu[N][N];
- double x[N];
- double b[N];
- int p[N];
- {
- int i, col, diag;
-
- double y[N];
- double temp;
-
- /* solve ly = b */
- for( diag=0; diag<=N-2; diag++ ) {
- if( p[diag] != diag ) {
- temp = b[diag];
- b[diag] = b[p[diag]];
- b[p[diag]] = temp;
- }
- }
-
- y[0] = b[0];
- for( diag=1; diag<=N-1; diag++ ) {
- y[diag] = b[diag];
- for( col=0; col<=diag-1; col++ )
- y[diag] += lu[diag][col]*y[col];
- }
-
- /* solve ux=y */
- x[N-1] = y[N-1]/lu[N-1][N-1];
- for( diag=N-2; diag>=0; diag-- ) {
- x[diag] = y[diag];
- for( col=diag+1; col<=N-1; col++ )
- x[diag] -= lu[diag][col]*x[col];
- x[diag] /= lu[diag][diag];
- }
-
- };
-
- composite factor_A(in A, in f, in B)
- double distributed A[Q][N][N] map slice;
- double distributed f[Q*N] map byBlock;
- double distributed B[Q][N][M] map slice;
- {
- int i,r;
- int p[N];
- double tempW[N];
- double tempB[N];
-
- /* decompose each block */
- seq_lu(A[id], p);
- seq_solve(A[id], &z[id*N], &f[id*N], p); /* z = A inv f */
-
- for (i=0; i<M; i++) { /* W = A inv B */
- tempB[] = B[id][][i];
- seq_solve(A[id], tempW, tempB, p);
- W[id][][i] = tempW[];
- }
- };
-
- composite form_sums( in C, out sumCW, out sumCz )
- double distributed C[Q][M][N] map slice;
- double distributed sumCW[M][M] map byRow;
- double distributed sumCz[M] map byElement;
- {
- double T[M];
- double T2[M];
- double Temp[M][M];
- int i;
- int r,c;
-
- /* sum C*W = J*/
- mat_mat_mult(C[id], W[id], Temp);
-
- Temp[][] = gsum( Temp[][] )#;
-
- for( i=id*M/Q; i<=id*M/Q + M/Q; i++) {
- sumCW[i][] = Temp[i][];
- }
-
- if( id==Q-1 ) {
- sumCW[M%Q+1][] = Temp[M%Q+1][];
- }
-
- /* sum c*z */
- for( r=0; r<=M-1; r++ ) {
- T[r] = 0;
- for( c=0; c<=N-1; c++ )
- T[r] += C[id][r][c]* z[id*N+c];
- }
-
- T2[] = gsum(T[])#;
-
- for( i=id*M/Q; i<=id*M/Q + M/Q; i++)
- sumCz[i] = T2[i];
-
- if( id==Q-1 )
- sumCz[M%Q+1] = T2[M%Q+1];
- };
-
- composite compute_xi( in xqp, out x )
- double distributed xqp[M] map all;
- double distributed x[Q*N] map byBlock;
- {
- int r,c;
-
- for( r=0; r<=N-1; r++ ) {
- x[id*N+r] = 0;
- for( c=0; c<=M-1; c++ )
- x[id*N+r] += W[id][r][c]*xqp[c];
- }
- neg_vec( &x[id*N], N );
- add_vec( &x[id*N], &z[id*N], N );
- };
- }
-
- environment host{
- double A[Q][N][N], B[Q][N][M], C[Q][M][N], P[M][M],
- fqp[M], f[Q*N], xqp[M], x[Q*N], b[M], RowPerm[M], sumCW[M][M],
- sumCz[M];
- FILE *InFile;
- char filename[256];
-
- void read_dvector( InFile, v, size )
- FILE *InFile;
- double *v;
- int size;
- {
- int i;
- double temp;
-
- for( i=0; i<=size-1; i++ )
- fscanf( InFile, "%lf\n", &v[i] );
- };
-
- void read_dmatrix( InFile, m, row, col )
- FILE *InFile;
- double *m;
- int row, col;
- {
- int r, c;
- for( r=0; r<=row-1; r++ )
- read_dvector( InFile, (double *) (m+r*col), col );
- };
-
- void read_dmatrices( InFile, ms, size, row, col )
- FILE *InFile;
- double *ms;
- int size, row, col;
- {
- int i;
-
- for( i=0; i<=size-1; i++ )
- read_dmatrix( InFile, (double *) (ms+i*row*col), row, col );
- };
-
- /*
- * read_data reads an ascii file containing the linear system.
- * File must be in the following form (n, m, q must be set in program):
- *
- * A1 <CR>
- * ...
- * Aq <CR>
- * B1 <CR>
- * ...
- * Bq <CR>
- * C1 <CR>
- * ...
- * Cq <CR>
- * P <CR>
- * f <CR>
- * fqp <CR>
- *
- * Note:
- *
- * Matrices must be listed in row order.
- *
- */
- void read_data( )
- void;
- {
- InFile = fopen( filename, "r" );
- read_dmatrices( InFile, A, Q, N, N );
- read_dmatrices( InFile, B, Q, N, M );
- read_dmatrices( InFile, C, Q, M, N );
- read_dmatrix( InFile, P, M, M );
- read_dvector( InFile, f, Q*N );
- read_dvector( InFile, fqp, M );
- };
-
- print_results()
- {
- int i, ii;
-
- printf( "Solution to System: \n" );
- /* print x1 to xq */
- for( i=0; i<=(Q*N)-1; i++ )
- printf( "%lf\n", x[i] );
- /* print xqp */
- for( i=0; i<=M-1; i++ )
- printf( "%lf\n", xqp[i] );
- };
-
- void main( argc, argv )
- int argc;
- char *argv[];
- {
- strcpy(filename,"input.dat");
-
- read_data();
- factor_A( A[][][], f[], B[][][])#;
- form_sums( C[][][], sumCW[][], sumCz[])#;
- form_J( sumCW[][], P[][] )#;
- form_b( b[], sumCz[], fqp[] )#;
- dist_lu( P[][], RowPerm[])#;
- dist_solve( P[][], xqp[], b[], RowPerm[])#;
- compute_xi(xqp[], x[])#;
- print_results();
- }
- }
-